module MarcTools
  class MarcConverter

    #TODO: Hash with {tag-number => {position  => subfield_code => [array of subfields]}}
    
    def tagname(tag)
      tag.sub(/\$.*/,"")      
    end
    
    def codename(tag)
      tag.sub(/.*\$/, "")
    end
    
    def is_number?(object)
      true if Float(object) rescue false
    end
    
    def getElements(input_hash,tag)
      t=tag.sub(/\$.*/,"")
      c=tag.sub(/.*\$/, "")
      mylist=[]
      if input_hash[t]
        positionlist=input_hash[t].keys.sort
        positionlist.each {|pos|
          if input_hash[t][pos].key?(c)
            mylist << input_hash[t][pos][c]
          end
        }
        if !mylist.empty?
          return mylist
        end
      end
    end

    def filter(input_hash, taglist=[])
      taglist.each{|tag|
        if tag.include?("$")
          t=tagname(tag)
                    c=codename(tag)
                    if input_hash.key?(t)
          input_hash[t].keys.each{|k|
            input_hash[t][k].delete(c)
          }
    end
        else
          input_hash.delete(tag)
        end
      }
      input_hash
    end
    
    

    def concat(input_hash,tag1, tag2, separator=" - ")
      t1=tag1.sub(/\$.*/,"")
            c1=tag1.sub(/.*\$/, "")
            t2=tag2.sub(/\$.*/,"")
            c2=tag2.sub(/.*\$/, "")
            input_hash[t1].keys.each{|k|
if input_hash[t1][k][c2]
              new_string=[input_hash[t1][k][c1]+input_hash[t1][k][c2]]
else

              new_string=[input_hash[t1][k][c1]]
end
            input_hash[t1][k][c1]=[new_string.join(separator)]
      }
      input_hash
    end
    
def removeTagbyValue(input_hash, oldtag,value)   
       t1=oldtag.sub(/\$.*/,"")
      c1=oldtag.sub(/.*\$/, "")      
      if input_hash.include?(t1)
      input_hash[t1].keys.each{|k|       
   if input_hash[t1][k][c1][0]==value
input_hash[t1].delete(k)
end
}
end
input_hash
end

    def updateElements(input_hash,tag, func)
      t=tag.sub(/\$.*/,"")
      c=tag.sub(/.*\$/, "")
      if input_hash.key?(t)

        positionlist=input_hash[t].keys.sort
        positionlist.each {|pos|
          if input_hash[t][pos].key?(c)
            input_hash[t][pos][c]=input_hash[t][pos][c].map {|e| func.call(e)}
          end
        }
      end
      input_hash
    end

def changeSubfieldCode(input_hash, oldtag,newtag)   
      t1=oldtag.sub(/\$.*/,"")
     c1=oldtag.sub(/.*\$/, "")
     t2=newtag.sub(/\$.*/,"")
     c2=newtag.sub(/.*\$/, "")
     if input_hash.include?(t1)
     input_hash[t1].keys.each{|k|       
  input_hash[t1][k][c2]=input_hash[t1][k][c1]
input_hash[t1][k].delete(c1)
}
end
input_hash
end

def removeSubfield(input_hash, oldtag)   
      t1=oldtag.sub(/\$.*/,"")
     c1=oldtag.sub(/.*\$/, "")
     if input_hash.include?(t1)
     input_hash[t1].keys.each{|k|
input_hash[t1][k].delete(c1)
}
end
input_hash
end
    


    
def moveTag(input_hash, oldtag,newtag)
      t1=oldtag.sub(/\$.*/,"")
      c1=oldtag.sub(/.*\$/, "")
      t2=newtag.sub(/\$.*/,"")
      c2=newtag.sub(/.*\$/, "")
  #Store field in subfield_array
      if input_hash.include?(t1)
        subfield_array=[]
        input_hash[t1].keys.each{|k|
          input_hash[t1][k].keys.each{|k2|       
          if k2==c1    
            subfield_array<<input_hash[t1][k]
            input_hash[t1].delete(k)
          else
            subfield_array<<input_hash[t1][k][c2]=[]
            input_hash[t1].delete(k)
          end
          }
        }  
        input_hash[t1].keys.each{|k|
        input_hash[t1][k].keys.each{|k2|    
          if k2==c2    
          #Create Hash-node from subfield-array 
            if subfield_array.size > 0
              input_hash[t1][k][c1]=[]      
              subfield_array.each {|d|      
                input_hash[t1][k][c1] << d[c1].join('')
              }
            end
          end
        }
      }     
      end
    input_hash
    end
 

def changeTag(input_hash,oldtag,newtag)
      input_hash.keys().each{|k|
        if k==oldtag
          input_hash[newtag]=input_hash[k]
          input_hash.delete(k)
        end
      }
      input_hash
    end

def removeTag(input_hash,oldtag)
      input_hash.keys().each{|k|
        if k==oldtag
          input_hash.delete(k)
        end
      }
      input_hash
    end

    
    
    
def insertTag(input_hash,tag, content)
  t=tag.sub(/\$.*/,"")
  c=tag.sub(/.*\$/, "")
  if input_hash.key?(t)
    input_hash[t].keys.each {|pos|
      if input_hash[t][pos].key?(c)
          input_hash[t].update({input_hash[t].keys.max+1 => {c =>[content]}})
          break
      else
        input_hash[t][pos].update({c =>[content]})
        break
      end          
    }            
  else
    if tag.include?('$')
      input_hash.update(t => {1 => {c =>[content]}})    
    else
      input_hash.update(t => [content])
    end
  end
      #}
  input_hash
end

    
    def xml_to_hash(xml_doc)
        #Returns Marc_Hash
        result_hash={}
        tag=nil
        cnt=1
        xml_doc.each_element{|e|
            result_hash.update({e.name=>e.content})
        }
        result_hash
      end

      
    def marc_to_hash(xml_doc)
      #Returns Marc_Hash
      result_hash={}
      tag=nil
      cnt=1
      xml_doc.each_element{|e|
        if e['tag']
          if e['tag']==tag
            cnt+=1
            code={}
            e.each{|s|
              if s.attributes?
                if !code.key?(s['code'])
                  code[s['code']]=[s.content]
                else
                  code[s['code']] <<s.content
                end
                code[s['code']]=[s.content]
              end            }
            result_hash[e['tag']][cnt]=code

          else
            cnt=1
            code={}

            if e.name!='controlfield'
              e.each{|s|
                if s.attributes?
                  if !code.key?(s['code'])
                    code[s['code']]=[s.content]
                  else
                    code[s['code']] <<s.content
                  end
                end
              }
              result_hash.update({e['tag']=>{cnt=> code}})
              tag=e['tag']
            else
              result_hash.update({e['tag']=>[e.content]})
            end
          end

        else
          result_hash.update({'000leader'=>e.content})
        end
      }
      result_hash
    end

    
    
    
    

  
  
  
    
    
    
    
    
def hash_to_marc(input_hash)
    xml=LibXML::XML::Document.new()
    xml.root = LibXML::XML::Node.new("collection")
    xml.root << record=LibXML::XML::Node.new("record")
    input_hash.keys.sort.each {|tag|
      if tag[0..1]=='00' and tag!='000leader'
        record  << field=LibXML::XML::Node.new("controlfield")
        field['tag']=tag
        field.content=input_hash[tag].join("")
      elsif tag=='000leader'
        record  << field=LibXML::XML::Node.new("leader")
        #field.content=input_hash['000leader']
        field.content="00910cdm#a2200253###4500"
elsif is_number?(tag)
        input_hash[tag].keys.sort.each{
          |pos|
          record  << field=LibXML::XML::Node.new("datafield")
          field['tag']=tag
          field['ind1']=" "
          field['ind2']=" "
          input_hash[tag][pos].keys.sort.each{ |c|
            if input_hash[tag][pos][c]
            if input_hash[tag][pos][c].size > 1 
              input_hash[tag][pos][c].each{ |n|
field << sub=LibXML::XML::Node.new("subfield")
sub['code']=c
sub.content=n
}              
            else
field << sub=LibXML::XML::Node.new("subfield")
sub['code']=c
sub.content=input_hash[tag][pos][c].join(", ")
end
            end
          }
        }
      end
    }
    xml
  end
  
    private :tagname, :codename
    
    
  end

end
